package ztcp

import (
	"fmt"
	"net"
	"svvenus/zlog"
	"svvenus/znet/zpack"
)

//Server服务类
type TcpServer struct {
	//服务器的名称
	Name string
	//tcp4 or other
	IPVersion string
	//服务绑定的IP地址
	IP string
	//服务绑定的端口
	Port int
	//当前Server的链接管理器
	ConnMgr *TcpConnManager
	//最大连接数
	MaxConn int
	//连接创建Hook函数
	OnConnStart func(conn *TcpConnection)
	//连接断开Hook函数
	OnConnStop func(conn *TcpConnection)
	//连接接收消息Hook函数
	OnMsgReceive func(conn *TcpConnection, msg *zpack.PackBuffer)
}

//创建服务
func NewTcpServer(host string, port int) *TcpServer {
	s := &TcpServer{
		Name:      "tcp服务",
		IPVersion: "tcp4",
		IP:        host,
		Port:      port,
		ConnMgr:   NewTcpConnManager(),
		MaxConn:   4000,
	}
	return s
}

//开启服务
func (s *TcpServer) Start() {
	fmt.Printf("Start Server name: %s,listenner at IP: %s, Port %d is starting\n", s.Name, s.IP, s.Port)

	//开启一个go去做服务端Linster业务
	go func() {
		//1 获取一个TCP的Addr
		addr, err := net.ResolveTCPAddr(s.IPVersion, fmt.Sprintf("%s:%d", s.IP, s.Port))
		if err != nil {
			zlog.Debug("resolve tcp addr err: ", err)
			return
		}

		//2 监听服务器地址
		listener, err := net.ListenTCP(s.IPVersion, addr)
		if err != nil {
			zlog.Debug("listen", s.IPVersion, "err", err)
			return
		}

		//已经监听成功
		zlog.Debug("Success, now listenning...")

		var cid uint32
		cid = 0

		//3 启动server网络连接业务
		for {
			//3.1 阻塞等待客户端建立连接请求
			conn, err := listener.AcceptTCP()
			if err != nil {
				zlog.Debug("Accept err ", err)
				continue
			}
			//zlog.Debug("Get conn remote addr = ", conn.RemoteAddr().String())

			//3.2 设置服务器最大连接控制,如果超过最大连接，那么则关闭此新的连接
			if s.ConnMgr.Len() >= s.MaxConn {
				conn.Close()
				continue
			}

			//3.3 处理该新连接请求的 业务 方法， 此时应该有 handler 和 conn是绑定的
			dealConn := NewTcpConntion(s, conn, cid)
			cid++

			//3.4 启动当前链接的处理业务
			go dealConn.Start()
		}
	}()
}

//停止服务
func (s *TcpServer) Stop() {
	zlog.Debug("Stop server , name ", s.Name)

	//将其他需要清理的连接信息或者其他信息 也要一并停止或者清理
	s.ConnMgr.ClearConn()
}

//执行连接创建Hook函数
func (s *TcpServer) CallOnConnStart(conn *TcpConnection) {
	if s.OnConnStart != nil {
		//zlog.Debug("---> CallOnConnStart....")
		s.OnConnStart(conn)
	}
}

//执行连接断开Hook函数
func (s *TcpServer) CallOnConnStop(conn *TcpConnection) {
	if s.OnConnStop != nil {
		//zlog.Debug("---> CallOnConnStop....")
		s.OnConnStop(conn)
	}
}

//执行接收消息Hook函数
func (s *TcpServer) CallOnMsgReceive(conn *TcpConnection, msg *zpack.PackBuffer) {
	if s.OnMsgReceive != nil {
		//zlog.Debug("---> CallOnMsgReceive....")
		s.OnMsgReceive(conn, msg)
	} else {
		zlog.Error("CallOnMsgReceive is nil")
	}
}
